﻿using UnityEngine;
using UnityEditor;
using System.IO;
using Chaos;
using System.Collections.Generic;

public class SimpleMeshUtil
{
    static SimplifyMeshPreview meshPreview = new SimplifyMeshPreview();

    static public void DoDelete(MeshSimplify meshSimplify)
    {
        meshSimplify.RestoreOriginalMesh(true, meshSimplify.MeshSimplifyRoot == null);
        MeshSimplifyEditor.RemoveChildMeshSimplifyComponents(meshSimplify);
    }

    static public void DoSaveMeshAssets(MeshSimplify meshSimplify, bool clearSimpComp = false,bool toPickUpFloder = true)
    {
        SaveMeshAssets(meshSimplify, clearSimpComp,toPickUpFloder);
    }

    static public void DoCompute(MeshSimplify meshSimplify)
    {
        meshPreview.Clear();
        meshPreview.AddObj(meshSimplify.gameObject);
        meshPreview.FillAMount = 0.55f;
        meshPreview.UpdateOther(true);
    }

    //==========================================================
    static void Progress(string strTitle, string strMessage, float fT)
    {
        int nPercent = Mathf.RoundToInt(fT * 100.0f);

        if (nPercent != s_nLastProgress || s_strLastTitle != strTitle || s_strLastMessage != strMessage)
        {
            s_strLastTitle = strTitle;
            s_strLastMessage = strMessage;
            s_nLastProgress = nPercent;

            if (EditorUtility.DisplayCancelableProgressBar(strTitle, strMessage, fT))
            {
                Simplifier.Cancelled = true;
            }
        }
    }

    static void OnEnable()
    {
        m_bComputeData = false;
        m_bComputeMesh = false;
        m_bDeleteData = false;
        m_bRemoveFromTree = false;
        m_bSetupNewRelevanceSphere = false;
    }

    static void RemoveChildMeshSimplifyComponents(MeshSimplify meshSimplify)
    {
        RemoveChildMeshSimplifyComponentsRecursive(meshSimplify.gameObject, meshSimplify.gameObject, true);
    }

    static void RemoveChildMeshSimplifyComponentsRecursive(GameObject root, GameObject gameObject, bool bRecurseIntoChildren)
    {
        MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();

        if (meshSimplify != null && meshSimplify.MeshSimplifyRoot != null)
        {
            if (Application.isEditor && Application.isPlaying == false)
            {
                UnityEngine.Object.DestroyImmediate(meshSimplify, true);
            }
            else
            {
                UnityEngine.Object.Destroy(meshSimplify);
            }
        }

        if (bRecurseIntoChildren)
        {
            for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
            {
                RemoveChildMeshSimplifyComponentsRecursive(root, gameObject.transform.GetChild(nChild).gameObject, true);
            }
        }
    }

    static void SaveMeshAssets(MeshSimplify meshSimplify,bool clearSimpComp = false, bool toPickUpFloder = true)
    {
        try
        {
                GameObject gameObject = meshSimplify.gameObject;

                if (meshSimplify.MeshSimplifyRoot == null/* && meshSimplify.m_bEnablePrefabUsage*/)
                {
                    string objPath = AssetDatabase.GetAssetPath(gameObject);
                    string strMeshAssetPath = objPath.Replace("\\", "/");

                    if(toPickUpFloder)
                    {
                        strMeshAssetPath = strMeshAssetPath.Replace("/ArtRes/", "/ArtResPickUp/");
                        strMeshAssetPath = strMeshAssetPath.Replace("/ClientRes/", "/ClientResPickUp/");
                    }

                    string cloneObjPath = strMeshAssetPath;

                    string strMeshDirName = System.IO.Path.GetDirectoryName(strMeshAssetPath) + "/Mesh/";
                    if (!Directory.Exists(strMeshDirName))
                        Directory.CreateDirectory(strMeshDirName);

                    strMeshAssetPath = strMeshDirName + Path.GetFileNameWithoutExtension(objPath) + ".mesh";
                    if (File.Exists(strMeshAssetPath))
                        File.Delete(strMeshAssetPath);

                    GameObject cloneObj = GameObject.Instantiate(gameObject);
                    string cloneObjDir = System.IO.Path.GetDirectoryName(cloneObjPath);
                    if (!Directory.Exists(cloneObjDir))
                        Directory.CreateDirectory(cloneObjDir);
                    if (File.Exists(cloneObjPath))
                        File.Delete(cloneObjPath);

                    //string strMeshAssetPath = meshSimplify.AssetPath;//333
                    //if (string.IsNullOrEmpty(strMeshAssetPath))
                    {
                        //Debug.Log("Showing file selection panel");
                        string path;
                        string name;
                        if (string.IsNullOrEmpty(strMeshAssetPath))
                        {
                            path = AssetDatabase.GetAssetPath(gameObject);
                            name = Path.GetFileNameWithoutExtension(path);
                            path = Path.GetDirectoryName(path);
                        }
                        else
                        {
                            path = strMeshAssetPath;
                            name = Path.GetFileNameWithoutExtension(path);
                            path = Path.GetDirectoryName(path);
                            int idx = name.LastIndexOf('_');
                            if (idx >= 0)
                            {
                                name = name.Remove(idx, name.Length - idx);
                            }
                        }
                        if (path.StartsWith("Assets/"))
                        {
                            path = path.Remove(0, 7);
                        }

                        //strMeshAssetPath = UnityEditor.EditorUtility.SaveFilePanelInProject("Save mesh asset(s)", name + "_" + meshSimplify.GetSimplifiedTriangleCount(true).ToString() + ".asset", "asset", "Please enter a file name to save the mesh asset(s) to", path);
                        if (strMeshAssetPath.Length == 0)
                        {
                            //Debug.LogWarning("strMeshAssetPath.Length == 0. User cancelled?");
                            return;
                        }

                        //Debug.Log("User selected " + strMeshAssetPath + " using panel.");

                        meshSimplify.AssetPath = strMeshAssetPath;
                    }

                    int nCounter = 0;

                MeshSimplify[] childs = cloneObj.GetComponentsInChildren<MeshSimplify>();
                int jnt = childs.Length;
                for (int j = 0; j < jnt; j++)
                {
                    MeshSimplify childMs = childs[j];

                    if (childMs == meshSimplify)
                        continue;

                    SerializedObject serObj = new SerializedObject(childMs);
                    serObj.FindProperty("_overrideRootSettings").boolValue = true;

                    serObj.ApplyModifiedProperties();
                }

                //Debug.Log("Saving files to " + strMeshAssetPath + ". Exists previously?: " + System.IO.File.Exists(strMeshAssetPath));
                SaveMeshAssetsRecursive(gameObject, cloneObj, -1, gameObject, strMeshAssetPath, true, System.IO.File.Exists(strMeshAssetPath), ref nCounter);

                if(clearSimpComp)
                {
                    for (int j = 0; j < jnt; j++)
                    {
                        MeshSimplify childMs = childs[j];

                        if (childMs == meshSimplify)
                            continue;

                        GameObject.DestroyImmediate(childMs);
                    }
                }

                PrefabUtility.SaveAsPrefabAsset(cloneObj, cloneObjPath);


                GameObject.DestroyImmediate(GameObject.Find(cloneObj.name));
            }
        }
        catch (System.Exception e)
        {
            Debug.LogError("Error saving mesh assets to disk: " + e.Message + " Stack: " + e.StackTrace);
            EditorUtility.ClearProgressBar();
            Simplifier.Cancelled = false;
        }

        EditorUtility.ClearProgressBar();
        UnityEditor.AssetDatabase.Refresh();
        Simplifier.Cancelled = false;
    }

    static bool SaveMeshAssetsRecursive(GameObject root, GameObject cloneObj, int nChild, GameObject gameObject, string strFile, bool bRecurseIntoChildren, bool bAssetAlreadyCreated, ref int nProgressElementsCounter)
    {
        if (gameObject == null || Simplifier.Cancelled)
        {
            return bAssetAlreadyCreated;
        }

        MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();


        if (meshSimplify != null && meshSimplify.SimplifiedMesh != null)
        {
            if (Simplifier.Cancelled)
            {
                return bAssetAlreadyCreated;
            }

            string objName = meshSimplify.name;
            Transform itmTran = cloneObj.transform.Find(objName);

            if(itmTran == null && gameObject.transform.parent == null)
            {
                if (cloneObj.GetComponent<MeshFilter>() != null)
                    itmTran = cloneObj.transform;
            }

            if (null != itmTran)
            {
                GameObject itmObj = itmTran.gameObject;

                SkinnedMeshRenderer objSkin = itmObj.GetComponent<SkinnedMeshRenderer>();
                MeshFilter meshF = itmObj.GetComponent<MeshFilter>();

               
                if (bAssetAlreadyCreated == false)
                {
                    UnityEditor.AssetDatabase.CreateAsset(meshSimplify.SimplifiedMesh, strFile);
                    Resources.UnloadAsset(meshSimplify.SimplifiedMesh);
                    meshSimplify.SimplifiedMesh = null;
                    bAssetAlreadyCreated = true;

                    if (null != objSkin)
                        objSkin.sharedMesh = AssetDatabase.LoadAssetAtPath<Mesh>(strFile);
                    else if (null != meshF)
                        meshF.sharedMesh = AssetDatabase.LoadAssetAtPath<Mesh>(strFile);
                }
                else
                {
                    UnityEditor.AssetDatabase.AddObjectToAsset(meshSimplify.SimplifiedMesh, strFile);
                    UnityEditor.AssetDatabase.ImportAsset(UnityEditor.AssetDatabase.GetAssetPath(meshSimplify.SimplifiedMesh));

                    if (null != objSkin)
                        objSkin.sharedMesh = meshSimplify.SimplifiedMesh;
                    else if (null != meshF)
                        meshF.sharedMesh = meshSimplify.SimplifiedMesh;
                }
            }

            nProgressElementsCounter++;
        }


        if (bRecurseIntoChildren)
        {
            for (int nChildi = 0; nChildi < gameObject.transform.childCount; nChildi++)
            {
                bAssetAlreadyCreated = SaveMeshAssetsRecursive(root, cloneObj, nChild, gameObject.transform.GetChild(nChildi).gameObject, strFile, bRecurseIntoChildren, bAssetAlreadyCreated, ref nProgressElementsCounter);
            }
        }

        return bAssetAlreadyCreated;
    }

    static void SetHideFlags(List<MeshSimplify> targets)
    {
        foreach (Object targetObject in targets)
        {
            MeshSimplify meshSimplify = targetObject as MeshSimplify;

            if (meshSimplify.MeshSimplifyRoot == null)
            {
                SetHideFlagsRecursive(meshSimplify.gameObject, meshSimplify.gameObject, true);
            }
        }
    }

    static void SetHideFlagsRecursive(GameObject root, GameObject gameObject, bool bRecurseIntoChildren)
    {
        MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();

        if (meshSimplify && meshSimplify.MeshSimplifier)
        {
            meshSimplify.MeshSimplifier.hideFlags = HideFlags.HideInInspector;
        }

        if (bRecurseIntoChildren)
        {
            for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
            {
                SetHideFlagsRecursive(root, gameObject.transform.GetChild(nChild).gameObject, true);
            }
        }
    }

    static bool m_bComputeData = false;
    static bool m_bComputeMesh = false;
    //bool m_bEnablePrefabUsage = false;
    //bool m_bDisablePrefabUsage = false;
    static bool m_bDeleteData = false;
    static bool m_bRemoveFromTree = false;
    static bool m_bSetupNewRelevanceSphere = false;

    static bool m_bPreviewOriginalMesh = false;

    static int s_nLastProgress = -1;
    static string s_strLastTitle = "";
    static string s_strLastMessage = "";
}
